{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From /tmp/ipykernel_14427/771947750.py:6: The name tf.Session is deprecated. Please use tf.compat.v1.Session instead.\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2022-06-10 20:58:40.312090: I tensorflow/core/platform/cpu_feature_guard.cc:145] This TensorFlow binary is optimized with Intel(R) MKL-DNN to use the following CPU instructions in performance critical operations:  SSE4.1 SSE4.2 AVX AVX2 FMA\n",
      "To enable them in non-MKL-DNN operations, rebuild TensorFlow with the appropriate compiler flags.\n",
      "2022-06-10 20:58:40.334041: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 3600050000 Hz\n",
      "2022-06-10 20:58:40.334808: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x55e9970b4130 initialized for platform Host (this does not guarantee that XLA will be used). Devices:\n",
      "2022-06-10 20:58:40.334836: I tensorflow/compiler/xla/service/service.cc:176]   StreamExecutor device (0): Host, Default Version\n",
      "OMP: Info #155: KMP_AFFINITY: Initial OS proc set respected: 0-11\n",
      "OMP: Info #216: KMP_AFFINITY: decoding x2APIC ids.\n",
      "OMP: Info #157: KMP_AFFINITY: 12 available OS procs\n",
      "OMP: Info #158: KMP_AFFINITY: Uniform topology\n",
      "OMP: Info #287: KMP_AFFINITY: topology layer \"LL cache\" is equivalent to \"socket\".\n",
      "OMP: Info #287: KMP_AFFINITY: topology layer \"L3 cache\" is equivalent to \"socket\".\n",
      "OMP: Info #287: KMP_AFFINITY: topology layer \"L2 cache\" is equivalent to \"core\".\n",
      "OMP: Info #287: KMP_AFFINITY: topology layer \"L1 cache\" is equivalent to \"core\".\n",
      "OMP: Info #192: KMP_AFFINITY: 1 socket x 6 cores/socket x 2 threads/core (6 total cores)\n",
      "OMP: Info #218: KMP_AFFINITY: OS proc to physical thread map:\n",
      "OMP: Info #172: KMP_AFFINITY: OS proc 0 maps to socket 0 core 0 thread 0 \n",
      "OMP: Info #172: KMP_AFFINITY: OS proc 6 maps to socket 0 core 0 thread 1 \n",
      "OMP: Info #172: KMP_AFFINITY: OS proc 1 maps to socket 0 core 1 thread 0 \n",
      "OMP: Info #172: KMP_AFFINITY: OS proc 7 maps to socket 0 core 1 thread 1 \n",
      "OMP: Info #172: KMP_AFFINITY: OS proc 2 maps to socket 0 core 2 thread 0 \n",
      "OMP: Info #172: KMP_AFFINITY: OS proc 8 maps to socket 0 core 2 thread 1 \n",
      "OMP: Info #172: KMP_AFFINITY: OS proc 3 maps to socket 0 core 3 thread 0 \n",
      "OMP: Info #172: KMP_AFFINITY: OS proc 9 maps to socket 0 core 3 thread 1 \n",
      "OMP: Info #172: KMP_AFFINITY: OS proc 4 maps to socket 0 core 4 thread 0 \n",
      "OMP: Info #172: KMP_AFFINITY: OS proc 10 maps to socket 0 core 4 thread 1 \n",
      "OMP: Info #172: KMP_AFFINITY: OS proc 5 maps to socket 0 core 5 thread 0 \n",
      "OMP: Info #172: KMP_AFFINITY: OS proc 11 maps to socket 0 core 5 thread 1 \n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14427 thread 0 bound to OS proc set 0\n",
      "2022-06-10 20:58:40.335531: I tensorflow/core/common_runtime/process_util.cc:115] Creating new thread pool with default inter op setting: 2. Tune using inter_op_parallelism_threads for best performance.\n"
     ]
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from sklearn import datasets\n",
    "sess = tf.Session()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "iris = datasets.load_iris()\n",
    "x_vals = np.array([[x[0], x[3]] for x in iris.data])\n",
    "y_vals = np.array([1 if y==0 else -1 for y in iris.target])\n",
    "class1_x = [x[0] for i,x in enumerate(x_vals) if y_vals[i]==1]\n",
    "class1_y = [x[1] for i,x in enumerate(x_vals) if y_vals[i]==1]\n",
    "class2_x = [x[0] for i,x in enumerate(x_vals) if y_vals[i]==-1]\n",
    "class2_y = [x[1] for i,x in enumerate(x_vals) if y_vals[i]==-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From /tmp/ipykernel_14427/4178710228.py:2: The name tf.placeholder is deprecated. Please use tf.compat.v1.placeholder instead.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "batch_size = 100\n",
    "x_data = tf.placeholder(shape=[None, 2], dtype=tf.float32)\n",
    "y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32)\n",
    "prediction_grid = tf.placeholder(shape=[None, 2], dtype=tf.float32)\n",
    "b = tf.Variable(tf.random.normal(shape=[1,batch_size]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "gamma = tf.constant(-10.0)\n",
    "dist = tf.reduce_sum(tf.square(x_data), 1)\n",
    "dist = tf.reshape(dist, [-1,1])\n",
    "sq_dists = tf.add(tf.subtract(dist, tf.multiply(2., tf.matmul(x_data, tf.transpose(x_data)))), tf.transpose(dist))\n",
    "my_kernel = tf.exp(tf.multiply(gamma, tf.abs(sq_dists)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "model_output = tf.matmul(b, my_kernel)\n",
    "first_term = tf.reduce_sum(b)\n",
    "b_vec_cross = tf.matmul(tf.transpose(b), b)\n",
    "y_target_cross = tf.matmul(y_target, tf.transpose(y_target))\n",
    "second_term = tf.reduce_sum(tf.multiply(my_kernel, tf.multiply(b_vec_cross, y_target_cross)))\n",
    "loss = tf.negative(tf.subtract(first_term, second_term))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "rA = tf.reshape(tf.reduce_sum(tf.square(x_data), 1),[-1,1])\n",
    "rB = tf.reshape(tf.reduce_sum(tf.square(prediction_grid), 1),[-1,1])\n",
    "pred_sq_dist = tf.add(tf.subtract(rA, tf.multiply(2., tf.matmul(x_data, tf.transpose(prediction_grid)))), tf.transpose(rB))\n",
    "pred_kernel = tf.exp(tf.multiply(gamma, tf.abs(pred_sq_dist)))\n",
    "prediction_output = tf.matmul(tf.multiply(tf.transpose(y_target),b), pred_kernel)\n",
    "prediction = tf.sign(prediction_output - tf.reduce_mean(prediction_output))\n",
    "accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.squeeze(prediction), tf.squeeze(y_target)), tf.float32))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From /tmp/ipykernel_14427/1332477025.py:1: The name tf.train.GradientDescentOptimizer is deprecated. Please use tf.compat.v1.train.GradientDescentOptimizer instead.\n",
      "\n",
      "WARNING:tensorflow:From /home/guoruiming/miniconda3/envs/tf1/lib/python3.7/site-packages/tensorflow_core/python/util/tf_should_use.py:198: initialize_all_variables (from tensorflow.python.ops.variables) is deprecated and will be removed after 2017-03-02.\n",
      "Instructions for updating:\n",
      "Use `tf.global_variables_initializer` instead.\n"
     ]
    }
   ],
   "source": [
    "my_opt = tf.train.GradientDescentOptimizer(0.01)\n",
    "train_step = my_opt.minimize(loss)\n",
    "init = tf.initialize_all_variables()\n",
    "sess.run(init)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14959 thread 1 bound to OS proc set 1\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14968 thread 2 bound to OS proc set 2\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14970 thread 4 bound to OS proc set 4\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14969 thread 3 bound to OS proc set 3\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14971 thread 5 bound to OS proc set 5\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14972 thread 6 bound to OS proc set 6\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14973 thread 7 bound to OS proc set 7\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14974 thread 8 bound to OS proc set 8\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14975 thread 9 bound to OS proc set 9\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14977 thread 11 bound to OS proc set 11\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14976 thread 10 bound to OS proc set 10\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14978 thread 12 bound to OS proc set 0\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14958 thread 13 bound to OS proc set 1\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14979 thread 14 bound to OS proc set 2\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14980 thread 15 bound to OS proc set 3\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14981 thread 16 bound to OS proc set 4\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14982 thread 17 bound to OS proc set 5\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14983 thread 18 bound to OS proc set 6\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14984 thread 19 bound to OS proc set 7\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14985 thread 20 bound to OS proc set 8\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14986 thread 21 bound to OS proc set 9\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14987 thread 22 bound to OS proc set 10\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14988 thread 23 bound to OS proc set 11\n",
      "OMP: Info #254: KMP_AFFINITY: pid 14427 tid 14989 thread 24 bound to OS proc set 0\n"
     ]
    }
   ],
   "source": [
    "loss_vec = []\n",
    "batch_accuracy = []\n",
    "for i in range(1300):\n",
    "    rand_index = np.random.choice(len(x_vals), size=batch_size)\n",
    "    rand_x = x_vals[rand_index]\n",
    "    rand_y = np.transpose([y_vals[rand_index]])\n",
    "    sess.run(train_step, feed_dict={x_data: rand_x, y_target: rand_y})\n",
    "    temp_loss = sess.run(loss, feed_dict={x_data: rand_x, y_target: rand_y})\n",
    "    loss_vec.append(temp_loss)\n",
    "\n",
    "    acc_temp = sess.run(accuracy, feed_dict={x_data: rand_x, y_target: rand_y, prediction_grid:rand_x})\n",
    "    batch_accuracy.append(acc_temp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_min, x_max = x_vals[:, 0].min() - 1, x_vals[:, 0].max() + 1\n",
    "y_min, y_max = x_vals[:, 1].min() - 1, x_vals[:, 1].max() + 1\n",
    "xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02), np.arange(y_min, y_max, 0.02))\n",
    "grid_points = np.c_[xx.ravel(), yy.ravel()]\n",
    "[grid_predictions] = sess.run(prediction, feed_dict={x_data: rand_x, y_target: rand_y, prediction_grid: grid_points})\n",
    "grid_predictions = grid_predictions.reshape(xx.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3.5, 8.5)"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.contourf(xx, yy, grid_predictions, cmap=plt.cm.Paired, alpha=0.8)\n",
    "plt.plot(class1_x, class1_y, 'ro', label='I. setosa')\n",
    "plt.plot(class2_x, class2_y, 'kx', label='Non setosa')\n",
    "plt.title('Gaussian SVM Results on Iris Data')\n",
    "plt.xlabel('Pedal Length')\n",
    "plt.ylabel('Sepal Width')\n",
    "plt.legend(loc='lower right')\n",
    "plt.ylim([-0.5, 3.0])\n",
    "plt.xlim([3.5, 8.5])"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "35d45d1db16ebad0710ab1697cb66eb90000ecea9566af6cb4ee4c767f56eaed"
  },
  "kernelspec": {
   "display_name": "Python 3.7.13 ('tf1')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.13"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
